WOLF core
WOLF: A Modular Estimation Framework for Robotics
XXXXXXXXXXXXXXXXXXXXXXXXvoid(0)" frameborder="0" name="MSearchResults" id="MSearchResults">
wolf::Factory< TypeBase, TypeInput > Class Template Reference

Singleton template factory. More...

#include <core/common/factory.h>

Public Types

typedef TypeBase(* CreatorCallback) (TypeInput... _input)
 

Public Member Functions

std::string getClass () const
 
 Factory (const Factory &)=delete
 
void operator= (Factory const &)=delete
 

Static Public Member Functions

static bool registerCreator (const std::string &_type, CreatorCallback createFn)
 
static bool unregisterCreator (const std::string &_type)
 
static bool isCreatorRegistered (const std::string &_type)
 
static TypeBase create (const std::string &_type, TypeInput... _input)
 
static void printAddress ()
 
static void printCallbacks ()
 
static std::list< std::string > getRegisteredKeys ()
 

Detailed Description

template<class TypeBase, typename... TypeInput>
class wolf::Factory< TypeBase, TypeInput >

Singleton template factory.

This template class implements a generic factory as a singleton.

Parameters
TypeBasebase type of all the objects created by the factory
TypeInputvariadic type for the input arguments.

Template specialization

  • The class is templatized on the class of the produced objects, TypeBase. The produced objects are always of a class deriving from TypeBase. The returned data is an object of type TypeBase. If you want a shared pointer to an object, then TypeBase must be the desired shared pointer.

    From now on we will assume that a typedef is defined: std::shared_ptr<Type> as TypePtr.

    For example, you may use as TypeBase the following types:

    • LandmarkBase: the Factory creates landmarks deriving from LandmarkBase and returns base pointers LandmarkBasePtr to them
    • SensorBase: the Factory creates sensor deriving from SensorBase and returns base pointers SensorBasePtr to them
    • XxxBase: the Factory creates objects deriving from XxxBase and returns pointers XxxBasePtr to them.
  • The class is variadic-templatized on the types of the input parameter of the creator, TypeInput:
    • std::string is used when the input parameter is a file name from which to read data (typically a YAML file).
    • `std::string, YAML::Node is used when nodes are build from parameters in a YAML node.
    • Any other variadic list of inputs is possible.
  • Examples of specific factories existing in Wolf are in factory_landmark.h, factory_map.h,
    {factory_processor.h````,}
    ````factory_tree_manager.h

Operation of the factory

Rationale

Once specialized, this factory can create objects of classes deriving from TypeBase.

‍For example, if you want to make a Landmark factory, set TypeBase = LandmarkBasePtr.
Then, the factory will create specific landmarks deriving from LandmarkBase.
The specific type of landmark (e.g. LandmarkCorner2d, LandmarkAHP, LandmarkPolyline2d, etc) is indicated by a

string that we call TYPE in this documentation.

Specific object creation is invoked by the method create(TYPE, params ... ), where

  • the TYPE of object to create is identified with a string. This string matches the name of the derived class.
  • the params may be provided in different forms, normally YAML node – see TypeInput.

The methods to create specific objects are called creators. Creators must be registered to the factory before they can be invoked for object creation.

This documentation shows you how to:

  • Define correct TYPE names
  • Access the factory
  • Write object creators
  • Register and unregister object creators to the factory
  • Create objects using the factory
  • Examples: Write and register a landmark creator for LandmarkPolyline2d.

Define correct TYPE names

We use a std::string with literally the same text as the derived class name, e.g.:

  • SensorCamera -> "SensorCamera"
  • SensorLaser2d -> "SensorLaser2d"
  • LandmarkPolyline2d -> "LandmarkPolyline2d"
  • etc.

Access the factory

The first thing to know is that we have defined typedefs for the templates that we are using. For example:

Singleton template factory.
Definition: factory.h:260
Factory< std::shared_ptr< StateBlock >, const Eigen::VectorXd &, bool > FactoryStateBlock
StateBlock factory class.
Definition: factory_state_block.h:81
Factory< LandmarkBasePtr, const YAML::Node &, const std::vector< std::string > & > FactoryLandmark
Definition: factory_landmark.h:29

Second to know, the Factory class is a singleton: it can only exist once in your application. To access it, we internally use the static method get(),

\code
Factory<MyTypeBase, MyTypeInput>::get()
\endcode

but this is a private method.

The interesting methods are designed static, and are the ones responsible for accessing the Factory instance via .get().

You must therefore call the methods you like statically, e.g. to create a landmark, you use:

\code
FactoryLandmark::create(TYPE, args...); // see below for creating objects ...
\endcode

Write creator methods (in your derived object classes)

The method LandmarkPolyline2d::create(...) exists in the LandmarkPolyline2d class as a static method. All these XxxXxx::create() methods need to have exactly the same API, regardless of the object type. The API puts into play the two template parameters:

static std::shared_ptr<TypeBase> create( const TypeInput& );
static TypeBase create(const std::string &_type, TypeInput... _input)
Definition: factory.h:335

This API includes elements defined as TypeInput, which might be one or more inputs.

For the two examples introduced before, the corresponding creators would be:

 \code
 static StateBlockPtr       create(const Eigen::VectorXd& _state, bool _fixed)
 static LandmarkBasePtr     create(const YAML::Node&  _lmk_yaml_node)
 \endcode

See further down for an implementation example.

Register object creators

Prior to invoking the creation of an object of a particular TYPE, you must register the creator for this type into the factory.

Registering object creators into the factory is done through registerCreator(). You provide an object TYPE string (above), and a pointer to a static method that knows how to create your specific object, e.g.:

\code
FactoryLandmark::registerCreator("LandmarkPolyline2d", LandmarkPolyline2d::create);
\endcode

Automatic registration

Currently, registering is performed in specific source files, object_xxxx.cpp. For example, in sensor_camera_yaml.cpp we find the line:

\code
const bool registered_camera_intr = FactoryParamsSensor::registerCreator("ParamsSensorCamera",

createParamsSensorCamera);

which is a static invocation (i.e., it is placed at global scope outside of the ParamsSensorCamera class).

Therefore, at application level, all objects that have a .cpp file compiled are automatically registered.

Unregister object creators

The method unregisterCreator() unregisters the ObjectXxx::create() method. It only needs to be passed the string of the object type.

\code
Factory<MyTypeBase, MyTypeInput>::unregisterCreator("ParamsSensorCamera");
\endcode

Create objects using the factory

Note: Prior to invoking the creation of a object of a particular type, you must register the creator for this type into the factory.

To create e.g. a LandmarkPolyline2d from a YAML node you type:

\code
LandmarkBasePtr lmk_ptr = Factory<LandmarkBasePtr, YAML::Node>::create("LandmarkPolyline2d", lmk_yaml_node);
\endcode

or even better, make use of the convenient typedefs:

\code
LandmarkBasePtr lmk_ptr = FactoryLandmark::create("LandmarkPolyline2d", lmk_yaml_node);
\endcode

Examples

Example 1: Writing the creator of LandmarkPolyline2d from a YAML node

You can find this code in the landmark_polyline_2d.cpp file.

// Creator (this method is static):
LandmarkBasePtr LandmarkPolyline2d::create(const YAML::Node& _lmk_node)
{
// Parse YAML node with lmk info and data
unsigned int id = _lmk_node["id"].as<unsigned int>();
int first_id = _lmk_node["first_id"].as<int>();
bool first_defined = _lmk_node["first_defined"].as<bool>();
bool last_defined = _lmk_node["last_defined"].as<bool>();
unsigned int npoints = _lmk_node["points"].size();
Eigen::MatrixXd points(2,npoints);
for (unsigned int i = 0; i < npoints; i++)
{
points.col(i) = _lmk_node["points"][i].as<Eigen::Vector2d>();
}
// Create a new landmark
LandmarkBasePtr lmk_ptr = std::make_shared<LandmarkPolyline2d>(points, first_defined, last_defined, first_id);
lmk_ptr->setId(id);
return lmk_ptr;
}

Example 2: Registering the creator of LandmarkPolyline2d from a YAML node

You can find this code in the landmark_polyline_2d.cpp file.

// Register landmark creator (put the register code inside an unnamed namespace):
namespace
{
const bool registered_lmk_polyline_2d = FactoryLandmark::registerCreator("LandmarkPolyline2d",
LandmarkPolyline2d::create);
}
static bool registerCreator(const std::string &_type, CreatorCallback createFn)
Definition: factory.h:309

More information

  • FactorySensorNode: typedef of this template to create Sensor classes deriving from SensorBase directly from YAML files.
  • FactoryProcessor: typedef of this template to create processor classes deriving from ProcessorBase directly from YAML files.
  • FactoryLandmark: typedef of this template to create landmarks deriving from LandmarkBase directly from YAML nodes.
  • Problem::loadMap() : to load a maps directly from YAML files.
  • You can also check the code in the example file src/examples/test_map_yaml.cpp.

See also

Member Typedef Documentation

◆ CreatorCallback

template<class TypeBase , typename... TypeInput>
typedef TypeBase(* wolf::Factory< TypeBase, TypeInput >::CreatorCallback) (TypeInput... _input)

Constructor & Destructor Documentation

◆ Factory()

template<class TypeBase , typename... TypeInput>
wolf::Factory< TypeBase, TypeInput >::Factory ( const Factory< TypeBase, TypeInput > &  )
delete

Member Function Documentation

◆ create()

template<class TypeBase , typename... TypeInput>
TypeBase wolf::Factory< TypeBase, TypeInput >::create ( const std::string &  _type,
TypeInput...  _input 
)
inlinestatic

◆ getClass()

std::string wolf::FactoryTreeManagerFile::getClass
inline

◆ getRegisteredKeys()

template<class TypeBase , typename... TypeInput>
std::list< std::string > wolf::Factory< TypeBase, TypeInput >::getRegisteredKeys
inlinestatic

◆ isCreatorRegistered()

template<class TypeBase , typename... TypeInput>
bool wolf::Factory< TypeBase, TypeInput >::isCreatorRegistered ( const std::string &  _type)
inlinestatic

◆ operator=()

template<class TypeBase , typename... TypeInput>
void wolf::Factory< TypeBase, TypeInput >::operator= ( Factory< TypeBase, TypeInput > const &  )
delete

◆ printAddress()

template<class TypeBase , typename... TypeInput>
void wolf::Factory< TypeBase, TypeInput >::printAddress
inlinestatic

◆ printCallbacks()

template<class TypeBase , typename... TypeInput>
void wolf::Factory< TypeBase, TypeInput >::printCallbacks
inlinestatic

◆ registerCreator()

template<class TypeBase , typename... TypeInput>
bool wolf::Factory< TypeBase, TypeInput >::registerCreator ( const std::string &  _type,
CreatorCallback  createFn 
)
inlinestatic

◆ unregisterCreator()

template<class TypeBase , typename... TypeInput>
bool wolf::Factory< TypeBase, TypeInput >::unregisterCreator ( const std::string &  _type)
inlinestatic

The documentation for this class was generated from the following files: